package leetcode.other;

/**
 * 整数数组的一个 排列  就是将其所有成员以序列或线性顺序排列。
 *
 * 例如，arr = [1,2,3] ，以下这些都可以视作 arr 的排列：[1,2,3]、[1,3,2]、[3,1,2]、[2,3,1] 。
 * 整数数组的 下一个排列 是指其整数的下一个字典序更大的排列。更正式地，如果数组的所有排列根据其字典顺序从小到大排列在一个容器中，那么数组的 下一个排列 就是在这个有序容器中排在它后面的那个排列。如果不存在下一个更大的排列，那么这个数组必须重排为字典序最小的排列（即，其元素按升序排列）。
 *
 * 例如，arr = [1,2,3] 的下一个排列是 [1,3,2] 。
 * 类似地，arr = [2,3,1] 的下一个排列是 [3,1,2] 。
 * 而 arr = [3,2,1] 的下一个排列是 [1,2,3] ，因为 [3,2,1] 不存在一个字典序更大的排列。
 * 给你一个整数数组 nums ，找出 nums 的下一个排列。
 *
 * 必须 原地 修改，只允许使用额外常数空间。
 */


public class A31 {
    //1  3  2

    public void nextPermutation(int[] nums) {
int n=nums.length;
int i=nums.length-2;
//从右往左找第一个小于其右边数的数字
        while(i>=0&&nums[i]>=nums[i+1])i--;
        if(i>=0){
            //说明找到了
int j=n-1;
            //从最右边找最小的且大于nums[i]的数，靠右且大于
            while(nums[j] <= nums[i])j--;
            swap(i,j,nums);
}
        //如果上一步产生交换当我们交换后，i右侧的数一定是单调递增,因为我们找的是第一个比nums[i]大的数字，所以nums[j]右侧的数<=nums[i]，且由于我们一开始的操作，i右边的数字是递增的,所以i后面的数字应该反转
     //如果没有交换,说明右到左递增，此时i=-1，调用方法整个反转
        reverse(nums,i+1,n-1);
    }
    void swap(int i,int j, int[] nums){
        int temp=nums[i];
        nums[i]=nums[j];
        nums[j]=temp;
    }
    void f(int[] nums){
        int i=0;
        int j=nums.length-1;
        int temp;
        while(i<j){
            temp=nums[i];
            nums[i]=nums[j];
            nums[j]=temp;
            i++;
            j--;
        }
    }
    private void reverse(int[] nums, int left, int right) {
        while (left < right) {
            swap( left++, right--,nums);
        }
    }
}
